<script lang="ts" module>
    export const MenuContextKey = Symbol("MenuContextKey");
    export const useMenuContext = () => getContext<MenuContextData>(MenuContextKey);
</script>

<script lang="ts">
    import { getContext, setContext, untrack } from "svelte";
    import { useClassList } from "../utils/useClassList";
    import type { MenuStore, MenuContextData, MenuProps } from "./Menu";
    import { useStyle } from "../utils/useStyle";

    let { activeName = $bindable(), collapsedWidth = 80, ...props }: MenuProps = $props();
    const accordion = $derived(props.accordion || false);
    const theme = $derived(props.theme || "light");
    const dir = $derived(props.dir || "v");

    // 创建存储
    const store = $state({
        openKeys: {},
        activeName: activeName,
        min: props.min,
    } as any);

    const classList = $derived(
        useClassList(props, "cm-menu", {
            [`cm-menu-${dir}`]: dir,
            [`cm-menu-min`]: props.min,
            [`cm-menu-${theme}`]: theme,
        }),
    );

    const styles = $derived(
        useStyle(props, {
            width: store.min ? `${collapsedWidth}px` : "",
        }),
    );

    const tree: any = [];
    const treeMap: any = {};

    // 更新父菜单的打开状态
    const updateParentOpenStatus = (name: string) => {
        let parent = treeMap && treeMap[name] && treeMap[name].parent;
        if (parent) {
            while (parent) {
                if (!store.openKeys[parent.name]) {
                    setOpen(parent.name);
                }
                parent = parent.parent;
            }
        } else {
            // 顶级菜单项 横向的时候， 设置打开项 可以关闭已打开的subMenu
            if (dir === "h" || store.min) {
                setOpen(name);
            }
        }
    };

    $effect(() => {
        const name = activeName;
        store.min;
        if (name) {
            store.activeName = name;
            // 父节点没打开的话进行打开
            untrack(() => {
                // 页面刷新的时候初始化需要延迟等待treeMap加载数据
                setTimeout(() => {
                    updateParentOpenStatus(name);
                });
            });
        }
    });

    // 更新min参数的副作用
    $effect(() => {
        store.min = props.min;
    });

    // 菜单点击处理
    const onSelect = (name: string, data: any) => {
        activeName = name;
        props.onselect?.(name, data);
    };

    // 子菜单是否存在已打开的
    const childrenOpen = (item: any, names: any) => {
        item.children &&
            item.children.forEach((aitem: any) => {
                if (store.openKeys[aitem.name]) {
                    names[aitem.name] = true;
                }
                childrenOpen(aitem, names);
            });
    };

    // 设置打开
    const setOpen = (name: string) => {
        if (accordion || dir === "h" || store.min) {
            if (store.openKeys[name]) {
                delete store.openKeys[name];
                return;
            }
            let item = treeMap[name];
            const names: any = { [name]: true };
            while (item.parent) {
                names[item.parent.name] = true;
                item = item.parent;
            }
            childrenOpen(item, names);
            const keys = Object.keys(store.openKeys);
            keys.forEach((key: string) => {
                if (!names[key]) {
                    delete store.openKeys[key];
                }
            });

            Object.assign(store.openKeys, names);
        } else {
            if (store.openKeys[name]) {
                delete store.openKeys[name];
            } else {
                store.openKeys[name] = true;
            }
        }
    };

    setContext(MenuContextKey, {
        level: 0,
        parentName: "__root",
        onSelect,
        getStore: () => store,
        setOpen,
        tree,
        treeMap,
        getTheme: () => theme,
        dir: () => dir,
    });
</script>

<ul class={classList} style={styles}>
    {@render props.children?.()}
</ul>
